home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Games / Glider 3.14 / source / Glider parts ƒ / E-GameUtilities.p < prev    next >
Encoding:
Text File  |  1993-06-03  |  31.8 KB  |  804 lines  |  [TEXT/PJMM]

  1. unit GameUtilities;
  2.  
  3. interface
  4.  
  5.     uses
  6.         Dialogs, Sound;
  7.  
  8.     const
  9.         maxLevel = 15;                {Here follow all the global constants.        }
  10.         defaultNumber = 4;
  11.         defaultRoomBegin = 1;
  12.         dartForwardFast = 8;
  13.         dartBackwardFast = -2;
  14.         gliderForwardFast = 4;
  15.         gliderBackwardFast = -4;
  16.         gravityFast = 2;
  17.         ceilingFast = 4;
  18.         floorFast = -6;
  19.         startHori = 0;
  20.         startVert = 20;
  21.         shadowVert = 288;
  22.  
  23.         fastSpeed = 1;
  24.         slowSpeed = 2;
  25.  
  26.         noSound = 0;
  27.         highPriority = 1;
  28.         lowPriority = 2;
  29.  
  30.         L_Apple = 201;                {Menu list}
  31.         C_About_Glider_2_0 = 1;
  32.         L_Game = 202;                {Menu list}
  33.         C_Start_Game = 1;
  34.         C_Start_in_Room = 2;
  35.         C_Pause = 4;
  36.         C_End_Game = 5;
  37.         C_Quit = 7;
  38.         L_Options = 203;            {Menu list}
  39.         C_Glider = 1;
  40.         C_Dart = 2;
  41.         C_Sound_On = 4;
  42.         C_Number_of_Gliders = 6;
  43.         C_Controls = 7;
  44.         C_Fast = 9;
  45.         C_Slow = 10;
  46.  
  47.     var        {And here are the global variables.  Many variables, huh?    }
  48.         leftControl, rightControl: Char;
  49.         moveHori, moveVert, soundPriority, gliderNumber, numberOfCandles: Integer;
  50.         thrust, stall, gravity, ductGravity, ventLift, totalObjects, levelOn: Integer;
  51.         switchH, switchV, gameTime, numberBegin, levelBegin, timeOfDeath: Integer;
  52.         burnMode, demoIndex, nextSwitch, levelHolding, numberHolding: Integer;
  53.         numberOfCopters, dripMode, dripCycle, advanceRate, catMode, gameSpeed: Integer;
  54.         theScore, oldScore, totalTime: LongInt;
  55.         stalling, doneFlag, Pausing, Playing, gliderCraft, soundOn: Boolean;
  56.         extraTime, darkOn, switchUntouched, extraGlider, candleThere: Boolean;
  57.         highScoresOut, burning, crushed, craftHolding, scoresChanged: Boolean;
  58.         soundPlaying, inhibitSound: Boolean;
  59.         nameUsing: Str255;
  60.             {Here follow the various offscreen and onscreen bitmap variables.    }
  61.         mainWindow: WindowPtr;
  62.         virginPort, loadPort, objectsPort, oldPort: GrafPtr;
  63.         virginBits, loadBits, objectsBits: Ptr;
  64.         virginMap, loadMap, objectsMap: BitMap;
  65.         virginArea, loadArea, objectsArea: Rect;
  66.             {Some rectangles...            }
  67.         playerDropRect, oldPlayerRect, shadowDropRect, oldShadowRect: Rect;
  68.         screenArea, horizonArea, catBodyRect, dangerRect, pawRect: Rect;
  69.         oldPawRect, vitalArea, playArea, dripDropRect, oldDripRect, escapeRect: Rect;
  70.             {The only sound global.        }
  71.         chanPtr: sndchannelptr;
  72.             {And all the arrays...        }
  73.         levelArray: packed array[1..15, 0..7, 1..4] of Integer;
  74.         eventArray: array[1..9] of Rect;
  75.         objectsRects: array[0..57, 0..1] of Rect;
  76.         objectArray, backgroundArray: array[1..15] of Integer;
  77.         candleInfo: array[0..2, 0..2] of Integer;
  78.         hiStrings: array[1..10] of Str255;
  79.         hiScores: array[1..10] of LongInt;
  80.         coptersRects: array[1..4, 0..1] of Rect;
  81.         copterMode: array[1..4, 0..1] of Integer;
  82.  
  83.             {Here are all the forwarded procedures and functions...        }
  84.     procedure DoTheSound (whichOne: Str255; priority: Integer);
  85.     function DoRandom (range: Integer): Integer;
  86.     procedure ResizeARect (var whichRect: Rect; whatNumber: Integer);
  87.     procedure ResetGliderPos;
  88.     procedure Init_GliderMain;
  89.     procedure Close_GliderMain;
  90.     procedure DrawAnObject (whichObject, hori, vert: Integer);
  91.     procedure SetUpFurniture;
  92.     procedure FoldTheGlider;
  93.     procedure Open_GliderMain;
  94.     procedure Update_GliderMain;
  95.     procedure ReDrawHiScores;
  96.     procedure ReadInScores (var prefs: Str255);
  97.     procedure WriteOutScores;
  98.  
  99. implementation
  100.  
  101. {=================================}
  102.  
  103.     function GetA5: LONGINT;
  104.     inline
  105.         $2E8D; {MOVE.L A5,(A7)}
  106.  
  107. {=================================}
  108.  
  109.     function LoadA5 (newA5: LONGINT): LONGINT;
  110.     inline
  111.         $2F4D, $0004, $2A5F;
  112.  
  113. {=================================}
  114.  
  115.     procedure ChanCallBack (chan: SndChannelPtr; cmd: SndCommand);
  116.         var
  117.             oldA5: LongInt;
  118.     begin
  119.         if cmd.param1 <> 12345 then
  120.             Exit(ChanCallBack);             { Skip err callBackCmd w/ System 6.0.4 }
  121.         oldA5 := LoadA5(cmd.param2);        { get the application's A5 and set it }
  122.         soundPlaying := FALSE;
  123.         soundPriority := noSound;
  124.         oldA5 := LoadA5(oldA5);            { restore old A5 }
  125.     end;
  126.  
  127. {=================================}
  128.  
  129.     procedure DoTheSound;
  130.         var
  131.             aCommand: SndCommand;
  132.             theSnd: Handle;
  133.             err: OSErr;
  134.     begin
  135.         if (not soundOn) then
  136.             Exit(DoTheSound);
  137.  
  138.         if (priority < soundPriority) then
  139.             Exit(DoTheSound);
  140.         soundPriority := priority;
  141.  
  142.         theSnd := GetNamedResource('snd ', whichOne);
  143.  
  144.         if (theSnd^ = nil) then
  145.             Exit(DoTheSound);
  146.  
  147.         MoveHHi(theSnd);
  148.         HLock(theSnd);
  149.  
  150.         if (chanPtr <> nil) then
  151.             begin
  152.                 with aCommand do
  153.                     begin
  154.                         cmd := quietCmd;
  155.                         param1 := 0;
  156.                         param2 := 0;
  157.                     end;
  158.                 err := SndDoImmediate(chanPtr, aCommand);
  159.                 err := SndDisposeChannel(chanPtr, TRUE);
  160.                 chanPtr := nil;
  161.             end;
  162.  
  163.         err := SndNewChannel(chanPtr, 0, 0, @ChanCallBack);
  164.         if (err = noErr) then
  165.             err := SndPlay(chanPtr, theSnd, TRUE);
  166.         with aCommand do
  167.             begin
  168.                 cmd := callBackCmd;
  169.                 param1 := 12345;
  170.                 param2 := GetA5;
  171.             end;
  172.         if (err = noErr) then
  173.             err := SndDoCommand(chanPtr, aCommand, FALSE);
  174.         if (err = noErr) then
  175.             soundPlaying := TRUE;
  176.  
  177.         HUnlock(theSnd);
  178.     end;
  179.  
  180. {=================================}
  181.  
  182.     function DoRandom;
  183.         var
  184.             rawResult: LongInt;
  185.     begin
  186.         rawResult := Abs(Random);                        {Straight out of "Macintosh Revealed."        }
  187.         DoRandom := (rawResult * range) div 32768    {Use it in your programs (esp. games).        }
  188.     end;
  189.  
  190. {=================================}
  191.  
  192.     procedure ResizeARect;
  193.         var
  194.             leftIs, topIs: Integer;
  195.     begin
  196.         leftIs := whichRect.left;                            {This is a routine to automatically resize    }
  197.         topIs := whichRect.top;                                {any rectangle passed to it.  For example,    }
  198.         whichRect := objectsRects[whatNumber, 0];    {a burning glider is > than a nonburning one.}
  199.         OffsetRect(whichRect, -whichRect.left + leftIs, -whichRect.top + topIs);
  200.     end;
  201.  
  202. {=================================}
  203.  
  204.     procedure ResetGliderPos;
  205.     begin
  206.         SetRect(playerDropRect, 0, 0, 0, 0);    {Here we set up the initial position of the glider    }
  207.         SetRect(shadowDropRect, 0, 0, 0, 0);    {We first predefine the rects at 0,0,0,0 ...         }
  208.         if (gliderCraft) then
  209.             begin
  210.                 ResizeARect(playerDropRect, 0);        {...and then we rely on ResizeARect to set the        }
  211.                 ResizeARect(shadowDropRect, 53);    {right side and bottom of the rectangle proper.        }
  212.             end
  213.         else
  214.             begin
  215.                 ResizeARect(playerDropRect, 2);        {The dart is larger and thus will have a larger        }
  216.                 ResizeARect(shadowDropRect, 54);    {bounding rectangle.                                    }
  217.             end;
  218.         OffsetRect(playerDropRect, startHori, startVert);        {Note that before being offset, the    }
  219.         OffsetRect(shadowDropRect, startHori, shadowVert);    {rectangles still reside in the upper    }
  220.         oldPlayerRect := playerDropRect;                            {left hand corner of the screen.        }
  221.         oldShadowRect := shadowDropRect;        {Here we've set the old rects equal to the new.    }
  222.     end;
  223.  
  224. {=================================}
  225.  
  226.     procedure Init_GliderMain;
  227.     begin
  228.         MainWindow := nil;                    {Cute, huh?  Prototyper does this.                }
  229.     end;
  230.  
  231. {=================================}
  232.  
  233.     procedure Close_GliderMain;
  234.     begin
  235.         DisposeWindow(MainWindow);        {Clear window and controls                        }
  236.         MainWindow := nil;                    {Make sure other routines know we are open    }
  237.     end;
  238.  
  239. {=================================}
  240.  
  241.     procedure DrawAnObject;                        {This routine is specifically designed for drawing    }
  242.         var                                                {the various furniture items.  Except for the case    }
  243.             tempRect, tempRect2, tempRect3: Rect;    {statement, the CopyBits & CopyMask routines    }
  244.     begin                                                {Are pretty generic.  These aren't for the flicker-}
  245.         case whichObject of                            {free animation we'll be doing when the game is    }
  246.             0..6, 8..13:                                         {underway, these calls simply draw the various    }
  247.                 begin                                            {objects from the objectMap to the virginMap.        }
  248.                     SetRect(tempRect, 0, 0, 0, 0);            {In effect, the objects become part of the back    -    }
  249.                     ResizeARect(tempRect, whichObject);    {ground.  Note: none of these procedures are seen    }
  250.                     OffsetRect(tempRect, hori, vert);        {by the player - we're copying from offscreen to    }
  251.                     CopyMask(objectsMap, objectsMap, virginMap, objectsRects[whichObject, 0], objectsRects[whichObject, 1], tempRect);
  252.                 end;                                            {offscreen.  Candles are the exception.                }
  253.             7, 14:         {Candles get special treatment}
  254.                 begin
  255.                     SetRect(tempRect, 0, 0, 0, 0);            {Why special?  We have a flickering flame to deal    }
  256.                     ResizeARect(tempRect, whichObject);    {with.  So, we have to CopyBits the bits behind    }
  257.                     OffsetRect(tempRect, hori, vert);        {the flame directly to the onscreen (thus hiding it)}
  258.                     tempRect2 := tempRect;                    {And then redraw the flame in it's "newly flick-    }
  259.                     OffsetRect(tempRect2, 0, -5);            {ered" location.  It's a rectangle nightmare!        }
  260.                     tempRect2.bottom := tempRect2.top + 20;
  261.                     CopyBits(virginMap, mainWindow^.portBits, tempRect2, tempRect2, srcCopy, nil);
  262.                     CopyMask(objectsMap, objectsMap, mainWindow^.portBits, objectsRects[whichObject, 0], objectsRects[whichObject, 1], tempRect);
  263.                 end;
  264.             99:        {this is the special case when the candle is first drawn - only}
  265.                 begin
  266.                     SetRect(tempRect, 0, 0, 0, 0);            {We do however want something of the candle to    }
  267.                     ResizeARect(tempRect, 7);                {be represented in the virginMap.  Otherwise, the    }
  268.                     OffsetRect(tempRect, hori, vert);        {candles won't be there when the room is first        }
  269.                     tempRect.top := tempRect.top + 13;        {revealed to the player (because we just CopyBits}
  270.                     tempRect2 := objectsRects[7, 0];        {the entire virginMap to the mainWindow).  So,    }
  271.                     tempRect2.top := tempRect2.top + 13;    {we draw the candle minus any specific flame to    }
  272.                     tempRect3 := objectsRects[7, 1];        {the virginMap.  Again, some sloppy rectangle        }
  273.                     tempRect3.top := tempRect3.top + 13;    {manipulation is required (to lose the flame).        }
  274.                     CopyMask(objectsMap, objectsMap, virginMap, tempRect2, tempRect3, tempRect);
  275.                 end;
  276.             otherwise
  277.                 begin
  278.                 end;
  279.         end;        {case whichObject of}
  280.     end;
  281.  
  282. {=================================}
  283.  
  284.     procedure SetUpFurniture;
  285.         var
  286.             Index, Ind2, xPos, yPos, anotherPos, addIt: Integer;
  287.             tempRect: Rect;
  288.             tempPoly: PolyHandle;
  289.     begin
  290.         candleThere := FALSE;                                    {Initially, there's no candle in the room    }
  291.         numberOfCandles := 0;                                    {And, initially, they total zero.            }
  292.         totalObjects := levelArray[levelOn, 0, 1];            {Get # of objects in room from array    }
  293.         addIt := 0;                                                {Additional items begins at zero.            }
  294.         for Index := 1 to totalObjects do                    {Now loop thru for each object in room    }
  295.             begin
  296.                 Ind2 := Index;                                            {We may need a second index                }
  297.                 case levelArray[levelOn, Index, 1] of            {One big long case statement handles     all}
  298.                     1:                                                         {the objects in the room.                    }
  299.                         begin                                                {1= a Wall socket                            }
  300.                             objectArray[Ind2] := 2;                        {2=glider will burn if in contact with    }
  301.                             xPos := levelArray[levelOn, Index, 2];        {Extract the horizontal and vertical        }
  302.                             yPos := levelArray[levelOn, Index, 3];        {from the data array for this room.        }
  303.                             DrawAnObject(3, xPos, yPos);                {Call drawing routine giving #, h and v.    }
  304.                             SetRect(eventArray[Ind2], xPos, yPos, xPos + 16, yPos + 24);    {Define it's rect    }
  305.                         end;
  306.                     2: 
  307.                         begin                                                {Floor vent                                    }
  308.                             objectArray[Ind2] := 1;                        {1=glider will be blown upwards                    }
  309.                             xPos := levelArray[levelOn, Index, 2];        {get vent's hori. pos. from data array    }
  310.                             DrawAnObject(4, xPos, 290);                    {object 4=the floor vent                    }
  311.                             SetRect(eventArray[Ind2], xPos + 12, levelArray[levelOn, Index, 3], xPos + 28, 295);
  312.                         end;
  313.                     3: 
  314.                         begin                                                {Ceiling suction vent                        }
  315.                             objectArray[Ind2] := 7;                        {7=glider is sucked back a few rooms    }
  316.                             xPos := levelArray[levelOn, Index, 2];        {get vent's hori. pos. from data array    }
  317.                             SetRect(eventArray[Ind2], xPos, 0, xPos + 48, 28);
  318.                             DrawAnObject(5, xPos, 10);                    {object 5=the ceiling suction vent                }
  319.                         end;
  320.                     4: 
  321.                         begin                                                {Ceiling blower                                }
  322.                             objectArray[Ind2] := 6;                        {6=glider will be blown downwards        }
  323.                             xPos := levelArray[levelOn, Index, 2];
  324.                             DrawAnObject(6, xPos, 10);
  325.                             SetRect(eventArray[Ind2], xPos + 12, 20, xPos + 28, levelArray[levelOn, Index, 3]);
  326.                         end;
  327.                     5: 
  328.                         begin                                                {Candle                                        }
  329.                             candleThere := TRUE;
  330.                             numberOfCandles := numberOfCandles + 1;
  331.                             objectArray[Ind2] := 2;                        {this area will cause glider to catch fire}
  332.                             xPos := levelArray[levelOn, Index, 2];
  333.                             yPos := levelArray[levelOn, Index, 3];
  334.                             candleInfo[numberOfCandles, 0] := xPos;            {Keep a global variable on the candle's    }
  335.                             candleInfo[numberOfCandles, 1] := yPos - 34;        {position and "mode".  This way we can    }
  336.                             candleInfo[numberOfCandles, 2] := DoRandom(6);    {redraw the "flickering flame" later.    }
  337.                             SetRect(eventArray[Ind2], xPos + 8, yPos - 45, xPos + 16, yPos);
  338.                             addIt := addIt + 1;                                {candles have 2 rects, so keep track of extra    }
  339.                             objectArray[totalObjects + addIt] := 1;        {this rectangle (if intersected) will lift glider    }
  340.                             SetRect(eventArray[totalObjects + addIt], xPos + 8, yPos - 100, xPos + 16, yPos - 65);
  341.                             DrawAnObject(99, xPos, yPos - 34)            {7 tells the procedure to draw a candle            }
  342.                         end;
  343.                     6: 
  344.                         begin                                                {Clock                                                    }
  345.                             objectArray[Ind2] := 8;                        {8=player gets a bonus in her/his score            }
  346.                             xPos := levelArray[levelOn, Index, 2];        {Get horizontal and vertical position from the    }
  347.                             yPos := levelArray[levelOn, Index, 3];        {data array (levelArray).                            }
  348.                             DrawAnObject(8, xPos, yPos - 28);            {8 means draw the clock                            }
  349.                             SetRect(eventArray[Ind2], xPos, yPos - 23, xPos + 23, yPos);
  350.                         end;
  351.                     7: 
  352.                         begin                                                {Folded paper                                        }
  353.                             objectArray[Ind2] := 9;                        {9=player gets an extra glider for touching it    }
  354.                             xPos := levelArray[levelOn, Index, 2];        {note: the first dimension of the array is         }
  355.                             yPos := levelArray[levelOn, Index, 3];        {indexed by the "levelOn" or room # now at.    }
  356.                             DrawAnObject(9, xPos, yPos - 21);            {Rectangle 9 in objectsRects = folded paper    }
  357.                             SetRect(eventArray[Ind2], xPos, yPos - 20, xPos + 48, yPos);
  358.                         end;
  359.                     8: 
  360.                         begin                                                {Thermostat}
  361.                             objectArray[Ind2] := 10;                        {10 means contact will turn on floor vents        }
  362.                             xPos := levelArray[levelOn, Index, 2];        {note: the 2nd dimension in levelArray is         }
  363.                             yPos := levelArray[levelOn, Index, 3];        {the # of the object we're on in the room        }
  364.                             DrawAnObject(10, xPos, yPos);
  365.                             SetRect(eventArray[Ind2], xPos, yPos, xPos + 16, yPos + 22);
  366.                             ventLift := 0;                                        {initially turn the vents off for this room        }
  367.                         end;
  368.                     9: 
  369.                         begin                                                {Shelf                                            }
  370.                             objectArray[Ind2] := 12;                        {crushed if glider intersects with it        }
  371.                             xPos := levelArray[levelOn, Index, 2];
  372.                             yPos := levelArray[levelOn, Index, 3];
  373.                             anotherPos := levelArray[levelOn, Index, 4];
  374.                             SetRect(eventArray[Ind2], xPos, yPos, anotherPos, yPos + 4);
  375.                             FillRect(eventArray[Ind2], gray);
  376.                             FrameRect(eventArray[Ind2]);
  377.                             tempPoly := OpenPoly;                            {draw shadow under shelf                    }
  378.                             MoveTo(xPos, yPos + 4);                        {start poly in one corner of shelf            }
  379.                             LineTo(anotherPos, yPos + 4);                {sweep to right under shelf                }
  380.                             LineTo(anotherPos, yPos);                        {move up right side a little ways            }
  381.                             LineTo(anotherPos + 12, ypos + 12);            {move down diagonally to the right        }
  382.                             LineTo(anotherPos + 12, yPos + 16);        {move down tiny bit for shadow of edge    }
  383.                             LineTo(xPos + 12, ypos + 16);                {sweep way left for bottom edge of shadow}
  384.                             LineTo(xPos, yPos + 4);                        {come up diagonally and close off the poly    }
  385.                             ClosePoly;                                        {stop using moves to define poly: close it    }
  386.                             FillPoly(tempPoly, dkGray);                    {throw the dark fray color into the poly            }
  387.                             KillPoly(tempPoly);                                {end of shadow drawing                    }
  388.                             DrawAnObject(11, xPos + 16, yPos + 4);    {draw the shelf brackets last                }
  389.                             DrawAnObject(11, anotherPos - 20, yPos + 4)
  390.                         end;
  391.                     10: 
  392.                         begin                                                {Table}
  393.                             objectArray[Ind2] := 12;                        {death by being crushed (fragile glider - eh?)    }
  394.                             xPos := levelArray[levelOn, Index, 2];
  395.                             yPos := levelArray[levelOn, Index, 3];
  396.                             anotherPos := levelArray[levelOn, Index, 4];
  397.                             SetRect(eventArray[Ind2], xPos, yPos, anotherPos, yPos + 7);
  398.                             FillRect(eventArray[Ind2], ltgray);
  399.                             FrameRect(eventArray[Ind2]);
  400.                             SetRect(tempRect, xPos, 305 - ((anotherPos - xPos) div 20), anotherPos, 305 + ((anotherPos - xPos) div 20));
  401.                             PenMode(srcOr);
  402.                             FillOval(tempRect, black);
  403.                             PenNormal;
  404.                             DrawAnObject(12, (xPos + anotherPos) div 2 - 24, 297);
  405.                             SetRect(tempRect, (xPos + anotherPos) div 2 - 2, yPos + 7, (xPos + anotherPos) div 2 + 1, 303);
  406.                             FillRect(tempRect, black)
  407.                         end;
  408.                     11: 
  409.                         begin                                                {Light switch}
  410.                             objectArray[Ind2] := 11;   {light switch has been encountered}
  411.                             switchH := levelArray[levelOn, Index, 2];
  412.                             switchV := levelArray[levelOn, Index, 3];
  413.                             DrawAnObject(13, switchH, switchV);
  414.                             SetRect(eventArray[Ind2], switchH, switchV, switchH + 16, switchV + 22);
  415.                             darkOn := TRUE;
  416.                         end;
  417.                 end  {end of case }
  418.             end;   {end of for loop}
  419.         totalObjects := totalObjects + addIt;    {Make sure totalObjects reflects the additional rects    }
  420.     end;                                            {due to candles dual rects (one burns & one lifts).        }
  421.  
  422. {=================================}
  423.  
  424.     procedure FoldTheGlider;
  425.         var
  426.             tempRect, tempRect2: Rect;
  427.             tempString: Str255;
  428.             index: Integer;
  429.             dummyLong: LongInt;
  430.     begin
  431.         SetPort(loadPort);                        {A tedious animation sequence to give us that wonderful    }
  432.         PenNormal;                                {folding plane.  First, we must set port to the loadPort    }
  433.         PenSize(2, 2);                            {to draw the white and framed rectangle that will slip    }
  434.         SetRect(tempRect, 0, 10, 80, 70);    {onto the scene.  We define it first...        }
  435.         EraseRect(tempRect);                    {Make it white (erase it's contents)...    }
  436.         FrameRect(tempRect);                    {Frame it with the 2 x 2 pen size...        }
  437.         SetRect(tempRect2, 0, 0, 0, 0);        {Define a blank "drop rect" for the sheet of paper...        }
  438.         ResizeARect(tempRect2, 41);            {And call ResizeARect to get it to the proper dimensions    }
  439.         OffsetRect(tempRect2, 20, 30);        {And now we move it to lie in the center of the 1st rect    }
  440.         CopyBits(objectsMap, loadMap, objectsRects[41, 0], tempRect2, srcCopy, nil);    {Draw it    }
  441.         MoveTo(25, 25);                        {And then align the pen - here comes the text.                }
  442.         TextFont(0);                                {Set font to the everyone-has Chicago 12                    }
  443.         TextSize(12);
  444.         NumToString(gliderNumber, tempString);        {Convert the # of glider to a character string    }
  445.         tempString := CONCAT(tempString, ' left');        {Add the characters ' left' (as in '5 left')        }
  446.         DrawString(tempString);                            {And finally draw it onto the first rectangle    }
  447.         tempRect2 := tempRect;                {We have now assembled the art on the loadMap and can    }
  448.         OffsetRect(tempRect2, -80, 0);        {scroll it out.  So first set up the drop rect (way left)    }
  449.         for index := 1 to 39 do                {and now we'll move the drop rect right, copy the art,    }
  450.             begin                                    {move the drop rect a little more right, copy the art,    }
  451.                 OffsetRect(tempRect2, 2, 0);        {etc... until the whole image has "scrolled" into view.    }
  452.                 CopyBits(loadMap, mainWindow^.portBits, tempRect, tempRect2, srcCopy, mainWindow^.visRgn);
  453.             end;
  454.         SetRect(tempRect2, 0, 0, 0, 0);        {Now that the "little window" appears on the left side of    }
  455.         ResizeARect(tempRect2, 41);            {the screen, we can begin erasing it, drawing the more-    }
  456.         OffsetRect(tempRect2, 18, 30);        {completely-folded glider, erase it, draw the more....    }
  457.         SetPort(mainWindow);                    {But first set the port to the on screen so that EraseRect}
  458.         InsetRect(tempRect, 2, 2);                {has a visible effect (else we would be erasing the        }
  459.         tempRect.top := tempRect.top + 17;    {area in the loadMap and not causing any visible erasing).}
  460.         tempRect.right := tempRect.right - 2;    {We rearrange tempRect's size so as not to erase the    }
  461.         for index := 41 to 52 do                {'5 left' message when we call EraseRect.                    }
  462.             begin
  463.                 Delay(6, dummyLong);                {Pause...    }
  464.                 ResizeARect(tempRect2, index);    {Get the proper size rect for the more-folded glider...    }
  465.                 if (index = 49) then
  466.                     OffsetRect(tempRect2, 0, 11);    {Folding phase 49, 50 and 52 need special adjusting.        }
  467.                 if (index = 50) then                    {Otherwise, the folding glider would jerk around on        }
  468.                     OffsetRect(tempRect2, 0, -1);    {the screen (the upper-left corner of the bounding rects    }
  469.                 if (index = 52) then                    {don't line up with the previous phases).                    }
  470.                     OffsetRect(tempRect2, 0, -3);
  471.                 EraseRect(tempRect);                {Here we go.  Erase all but the '5 left' (or '4 left' etc..).    }
  472.                 CopyBits(objectsMap, mainWindow^.portBits, objectsRects[index, 0], tempRect2, srcCopy, nil);
  473.                 DoTheSound('fold.snd', highPriority);        {And call the folding sound up "fwip"!                        }
  474.             end;
  475.         Delay(10, dummyLong);                {When done folding the glider, wait 1/3 of a second...        }
  476.         tempRect.top := tempRect.top - 17;    {Pop that tempRect back to it's original size...                }
  477.         tempRect.right := tempRect.right + 2;{Enlarge it to include the "frame" we drew and then        }
  478.         InsetRect(tempRect, -3, -3);            {CopyBits from the virginMap to screen (cover it all up).}
  479.         CopyBits(virginMap, mainWindow^.portBits, tempRect, tempRect, srcCopy, nil);
  480.     end;
  481.  
  482. {=================================}
  483.  
  484.     procedure UpDate_GliderMain;
  485.         var
  486.             whichBack: Integer;
  487.             Pic_Handle: PicHandle;
  488.             tempRect: Rect;
  489.     begin
  490.         SetPort(virginPort);
  491.         EraseRect(virginPort^.portRect);
  492.         whichBack := backgroundArray[levelOn];
  493.         SetRect(tempRect, 0, 0, 512, 322);
  494.         ClipRect(tempRect);
  495.         Pic_Handle := GetPicture(whichBack);        {Get Picture into memory            }
  496.         if (Pic_Handle <> nil) then                    {Only use handle if it is valid        }
  497.             begin
  498.                 HLock(Handle(Pic_Handle));                    {Lock the handle before using it    }
  499.                 tempRect := Pic_Handle^^.picFrame;
  500.                 DrawPicture(Pic_Handle, tempRect);        {And draw it to the virginMap        }
  501.                 ReleaseResource(Handle(Pic_Handle));        {Free up the memory we had held}
  502.                 HUnLock(Handle(Pic_Handle));                {Unlock the picture again}
  503.             end
  504.         else
  505.             SysBeep(3);
  506.         SetRect(tempRect, 0, 0, 1023, 1023);        {Widen the clip area again            }
  507.         ClipRect(tempRect);                                {Set the clip area                    }
  508.         SetUpFurniture;                                    {Draw the furniture there also..    }
  509.         if (darkOn) and (switchUntouched) then
  510.             begin
  511.                 FillRect(virginMap.bounds, black);            {Unless the lights are off, then        }
  512.                 DrawAnObject(13, switchH, switchV);    {we want blackness and the switch.    }
  513.             end;
  514. {And finally dump the whole virginMap collage to the mainWindow for player's perusal}
  515.         CopyBits(virginMap, mainWindow^.portBits, virginMap.bounds, mainWindow^.portRect, srcCopy, mainWindow^.visRgn);
  516.         if (levelOn = 15) then
  517.             begin
  518.                 CopyBits(virginMap, loadMap, catBodyRect, catBodyRect, srcCopy, nil);
  519.                 CopyMask(objectsMap, objectsMap, loadMap, objectsRects[28, 0], objectsRects[28, 1], catBodyRect);
  520.                 CopyBits(loadMap, mainWindow^.portBits, catBodyRect, catBodyRect, srcCopy, nil);
  521.             end;
  522.     end;
  523.  
  524. {=================================}
  525.  
  526.     procedure Open_GliderMain;
  527.     begin
  528.         if (mainWindow = nil) then        {Handle an open when already opened    }
  529.             begin
  530.                 mainWindow := GetNewWindow(1, nil, Pointer(-1));
  531.                 MoveWindow(mainWindow, (screenBits.bounds.right - 512) div 2, (screenBits.bounds.bottom - 342) div 2 + 20, FALSE);
  532.                 ShowWindow(mainWindow);
  533.                 SelectWindow(mainWindow);
  534.                 SetPort(mainWindow);
  535.                 UpDate_GliderMain;
  536.             end                                    {End for if (mainWindow<>nil)                }
  537.         else
  538.             SelectWindow(mainWindow);        {Already open, so show it                    }
  539.     end;
  540.  
  541. {=================================}
  542.  
  543.     procedure ReDrawHiScores;
  544.         var
  545.             index: Integer;
  546.             tempRect, dummyRect, dummyRect2, dummyRect3: Rect;
  547.             dummyString: Str255;
  548.     begin
  549.         SetPort(loadPort);                        {Set all drawing operations to go to the load Port offscreen    }
  550.         EraseRect(loadMap.bounds);            {What we're going to do here is move a copy of the glider    }
  551.         SetRect(dummyRect, 0, 0, 0, 0);        {with the banner to the load port from the object port, then    }
  552.         ResizeARect(dummyRect, 34);        {we'll write a message on it there and animate the whole    }
  553.         CopyBits(objectsMap, loadMap, objectsRects[34, 0], dummyRect, srcCopy, nil);
  554.         PenNormal;                                {banner-with-message across the "on-screen".                }
  555.         TextFont(0);                                {First we'll animate the one moving across the bottom with    }
  556.         TextSize(12);                            {my name on it, then we'll animate one higher up the screen    }
  557.         MoveTo(60, 14);                        {with the High Scores message.  Finally we'll draw a white    }
  558.         dummyString := '© 1989 - 93 john calhoun';
  559.         DrawString(dummyString);            {rectangle between the two and write all the hi scores on    }
  560.         dummyRect2 := dummyRect;            {it.  This kind of stuff is time consuming to write and takes    }
  561.         OffsetRect(dummyRect2, 512, 229);{up a good chunk of memory, but for the final product, but    }
  562.         dummyRect3 := dummyRect2;
  563.         dummyRect2.right := dummyRect2.right + 10;        {it seems to be worth it.                            }
  564.         for index := 90 downto 0 do            {These steps I'm passing over are all repeated and            }
  565.             begin                                    {documented below.  It's the same routine.                        }
  566.                 OffsetRect(dummyRect2, -3, 0);
  567.                 OffsetRect(dummyRect3, -3, 0);
  568.                 CopyBits(virginMap, loadMap, dummyRect2, dummyRect2, srcCopy, nil);
  569.                 CopyMask(loadMap, objectsMap, loadMap, dummyRect, objectsRects[34, 1], dummyRect3);
  570.                 CopyBits(loadMap, mainWindow^.portBits, dummyRect2, dummyRect2, srcCopy, mainWindow^.visRgn);
  571.             end;
  572.         SetRect(dummyRect, 0, 0, 0, 0);            {Set up an initially null rectangle                                }
  573.         ResizeARect(dummyRect, 34);            {Pass to ResizeARect to get the proper dimensions        }
  574.         CopyBits(objectsMap, loadMap, objectsRects[34, 0], dummyRect, srcCopy, nil);    {Copy to load    }
  575.         MoveTo(60, 14);                            {Get ready to write on the banner now in the load port    }
  576.         dummyString := 'Glider+ 3.14 High Scores...';    {Set dummyString to this string on banner            }
  577.         DrawString(dummyString);                {Draw it                                                            }
  578.         dummyRect2 := dummyRect;                {We'll need another ("drop") rect that's the same size    }
  579.         OffsetRect(dummyRect2, 512, 61);        {Start "drop" rect all the way right and down 61 pixels    }
  580.         dummyRect3 := dummyRect2;
  581.         dummyRect2.right := dummyRect2.right + 10;        {Add extra pixels to cover trail left behind        }
  582.         for index := 0 to 90 do                    {This loop will animate the glider-with-banner across    }
  583.             begin                                        {the top of the screen.                                            }
  584.                 OffsetRect(dummyRect2, -3, 0);        {Move the "drop" rect 3 pixels to left every loop            }
  585.                 OffsetRect(dummyRect3, -3, 0);        {Also move this "drop" rect.  MacII's scale CopyMask    }
  586.                 CopyBits(virginMap, loadMap, dummyRect2, dummyRect2, srcCopy, nil);
  587.                 CopyMask(loadMap, objectsMap, loadMap, dummyRect, objectsRects[34, 1], dummyRect3);
  588.                 CopyBits(loadMap, mainWindow^.portBits, dummyRect2, dummyRect2, srcCopy, mainWindow^.visRgn);
  589.             end;
  590.         SetPort(mainWindow);        {Make all drawing operations go to the screen        }
  591.         PenNormal;                    {Reset the pen to normal in case it's wigged out    }
  592.         PenSize(2, 2);                {Now make a thicker pen for a bolder line            }
  593.         TextFont(0);                    {Set font to Chicago (everyone has this font)        }
  594.         TextSize(12);                {Make it 12 point in size so that it isn't cruddy    }
  595.         SetRect(tempRect, 310, 80, 512, 232);    {Define rectangle for scores        }
  596.         EraseRect(tempRect);        {Erase this area on the screen (tabla rasa)            }
  597.         MoveTo(310, 80);            {Move the pen to the top left edge of the rect        }
  598.         LineTo(310, 230);            {Draw a line down along the left edge of the rect    }
  599.         for index := 1 to 10 do    {Now we're going to loop through all the scores    }
  600.             begin
  601.                 MoveTo(320, index * 15 + 77);            {Moving the pen down each time    }
  602.                 DrawString(hiStrings[index]);                {Draw the name of person        }
  603.                 MoveTo(450, index * 15 + 77);            {Move pen over to the right        }
  604.                 NumToString(hiScores[index], dummyString);
  605.                 DrawString(dummyString);                    {And draw their score            }
  606.             end;                            {Copy the screen to the virgin port for updates    }
  607.         CopyBits(mainWindow^.portBits, virginMap, screenArea, screenArea, srcCopy, nil);
  608.     end;
  609.  
  610. {=================================}
  611.  
  612.     procedure ReadInScores;
  613.  
  614.         type
  615.             scoreHandle = ^scorePtr;
  616.             scorePtr = ^score;
  617.             score = record
  618.                     data: array[0..9] of LongInt;
  619.                 end;
  620.  
  621.             nameHandle = ^namePtr;
  622.             namePtr = ^name;
  623.             name = record
  624.                     data: array[0..9, 0..14] of Char;
  625.                 end;
  626.  
  627.             prefHandle = ^prefPtr;
  628.             prefPtr = ^pref;
  629.             pref = record
  630.                     isFast, isNoisy: Boolean;
  631.                     isLeft, isRight: Char;
  632.                     isName: string[15];
  633.                 end;
  634.  
  635.         var
  636.             index, index2, tempVolume: Integer;
  637.             dummyStr: Str255;
  638.             theScores: scoreHandle;
  639.             theNames: nameHandle;
  640.             thePrefs: prefHandle;
  641.  
  642.     begin
  643.         theScores := scoreHandle(NewHandle(SIZEOF(score)));
  644.         MoveHHi(Handle(theScores));
  645.         HLock(Handle(theScores));
  646.         Handle(theScores) := GetResource('scrs', 128);
  647.         for index := 0 to 9 do
  648.             hiScores[index + 1] := theScores^^.data[index];
  649.         HUnlock(Handle(theScores));
  650.         ReleaseResource(Handle(theScores));
  651.         DisposHandle(Handle(theScores));
  652.  
  653.         theNames := nameHandle(NewHandle(SIZEOF(name)));
  654.         MoveHHi(Handle(theNames));
  655.         HLock(Handle(theNames));
  656.         Handle(theNames) := GetResource('name', 128);
  657.         for index := 0 to 9 do
  658.             begin
  659.                 dummyStr := '';
  660.                 for index2 := 0 to 14 do
  661.                     dummyStr := CONCAT(dummyStr, theNames^^.data[index, index2]);
  662.                 hiStrings[index + 1] := dummyStr;
  663.             end;
  664.         HUnlock(Handle(theNames));
  665.         ReleaseResource(Handle(theNames));
  666.         DisposHandle(Handle(theNames));
  667.  
  668.         thePrefs := prefHandle(NewHandle(SIZEOF(pref)));
  669.         MoveHHi(Handle(thePrefs));
  670.         HLock(Handle(thePrefs));
  671.         Handle(thePrefs) := GetResource('pref', 128);
  672.  
  673.         if ((thePrefs <> nil) and (resError = noErr)) then
  674.             begin
  675.  
  676.                 with thePrefs^^ do
  677.                     begin
  678.                         if (isFast) then
  679.                             gameSpeed := fastSpeed
  680.                         else
  681.                             gameSpeed := slowSpeed;
  682.  
  683.                         if (isNoisy) then
  684.                             soundOn := TRUE
  685.                         else
  686.                             soundOn := FALSE;
  687.                         if (inhibitSound) then
  688.                             soundOn := FALSE;
  689.                         GetSoundVol(tempVolume);
  690.                         if (tempVolume = 0) then
  691.                             soundOn := FALSE;
  692.  
  693.                         leftControl := isLeft;
  694.                         rightControl := isRight;
  695.  
  696.                         nameUsing := isName;
  697.                     end;
  698.  
  699.                 HUnlock(Handle(thePrefs));
  700.                 ReleaseResource(Handle(thePrefs));
  701.                 DisposHandle(Handle(thePrefs));
  702.             end
  703.         else
  704.             begin
  705.                 gameSpeed := fastSpeed;
  706.                 soundOn := not inhibitSound;
  707.                 leftControl := ',';
  708.                 rightControl := '.';
  709.                 nameUsing := 'Anonymous      ';
  710.             end;
  711.     end;
  712.  
  713. {=================================}
  714.  
  715.     procedure WriteOutScores;
  716.         type
  717.             scoreHandle = ^scorePtr;
  718.             scorePtr = ^score;
  719.             score = record
  720.                     data: array[0..9] of LongInt;
  721.                 end;
  722.  
  723.             nameHandle = ^namePtr;
  724.             namePtr = ^name;
  725.             name = record
  726.                     data: array[0..9, 0..14] of Char;
  727.                 end;
  728.  
  729.             prefHandle = ^prefPtr;
  730.             prefPtr = ^pref;
  731.             pref = record
  732.                     isFast, isNoisy: Boolean;
  733.                     isLeft, isRight: Char;
  734.                     isName: string[15];
  735.                 end;
  736.  
  737.         var
  738.             index, index2: Integer;
  739.             dummyStr: Str255;
  740.             theScores: scoreHandle;
  741.             theNames: nameHandle;
  742.             thePrefs: prefHandle;
  743.  
  744.     begin
  745.         thePrefs := prefHandle(NewHandle(SIZEOF(pref)));
  746.         HLock(Handle(thePrefs));
  747.         Handle(thePrefs) := GetResource('pref', 128);
  748.  
  749.         if ((thePrefs = nil) or (ResError <> noErr)) then
  750.             AddResource(Handle(thePrefs), 'pref', 128, 'added');
  751.  
  752.         with thePrefs^^ do
  753.             begin
  754.                 isFast := (gameSpeed = fastSpeed);
  755.  
  756.                 isNoisy := soundOn;
  757.  
  758.                 isLeft := leftControl;
  759.                 isRight := rightControl;
  760.  
  761.                 isName := COPY(nameUsing, 1, 15);
  762.             end;
  763.  
  764.         ChangedResource(Handle(thePrefs));
  765.         WriteResource(Handle(thePrefs));
  766.         HUnlock(Handle(thePrefs));
  767.         ReleaseResource(Handle(thePrefs));
  768.         DisposHandle(Handle(thePrefs));
  769.  
  770.         ChangedResource(Handle(thePrefs));
  771.         WriteResource(Handle(thePrefs));
  772.         HUnlock(Handle(thePrefs));
  773.         ReleaseResource(Handle(thePrefs));
  774.         DisposHandle(Handle(thePrefs));
  775.  
  776.         theScores := scoreHandle(NewHandle(SIZEOF(score)));
  777.         MoveHHi(Handle(theScores));
  778.         HLock(Handle(theScores));
  779.         Handle(theScores) := GetResource('scrs', 128);
  780.         for index := 0 to 9 do
  781.             theScores^^.data[index] := hiScores[index + 1];
  782.         ChangedResource(Handle(theScores));
  783.         WriteResource(Handle(theScores));
  784.         HUnlock(Handle(theScores));
  785.         ReleaseResource(Handle(theScores));
  786.         DisposHandle(Handle(theScores));
  787.  
  788.         theNames := nameHandle(NewHandle(SIZEOF(name)));
  789.         HLock(Handle(theNames));
  790.         Handle(theNames) := GetResource('name', 128);
  791.         for index := 0 to 9 do
  792.             for index2 := 0 to 14 do
  793.                 theNames^^.data[index, index2] := COPY(hiStrings[index + 1], index2 + 1, 1);
  794.         ChangedResource(Handle(theNames));
  795.         WriteResource(Handle(theNames));
  796.         HUnlock(Handle(theNames));
  797.         ReleaseResource(Handle(theNames));
  798.         DisposHandle(Handle(theNames));
  799.     end;
  800.  
  801.  
  802. {=================================}
  803.  
  804. end.